package com.company.graph;

import java.util.*;

public class NopowerNoDirectEdgeGraph implements EdgeGraph {
    private HashMap<Integer, List<PowerEdge>> adjs;
    private int edgeTotal = 0;

    public NopowerNoDirectEdgeGraph() {
        adjs = new HashMap<>();
    }

    /**
     * v represents the node v
     * w represents the node w
     * the edge is  "v - w"
     */
    @Override
    public void addEdge(int v, int w) {
        this.addEdge(v, w, 0);
    }

    @Override
    public void addEdge(int v, int w, double power) {
        if (v == w) {
            return;
        }
        List<PowerEdge> vEdges = getListById(v);
        List<PowerEdge> wEdges = getListById(w);
        if (getEdge(v, w) == null) {
            PowerEdge edge = new PowerEdge(v, w, power);
            vEdges.add(edge);
            wEdges.add(edge);
            edgeTotal++;
        }
    }

    private List<PowerEdge> getListById(int id) {
        List<PowerEdge> vEdges;
        if (adjs.containsKey(id)) {
            vEdges = adjs.get(id);
        } else {
            vEdges = new LinkedList<>();
            adjs.put(id, vEdges);
        }
        return vEdges;
    }

    @Override
    public void deleteEdge(int v, int w) {
        List<PowerEdge> vList = getListById(v);
        List<PowerEdge> wList = getListById(w);
        for (PowerEdge powerEdge : vList) {
            powerEdge.isSameWithNodirection(v, w);
            vList.remove(powerEdge);
        }
        for (PowerEdge powerEdge : wList) {
            powerEdge.isSameWithNodirection(v, w);
            wList.remove(powerEdge);
        }
    }

    @Override
    public String display() {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Integer, List<PowerEdge>> entry : adjs.entrySet()) {
            Integer v = entry.getKey();
            sb.append(v);
            sb.append(' ');
            List<PowerEdge> list = entry.getValue();
            for (PowerEdge edge : list) {
                sb.append(edge.other(v));
                sb.append(' ');
            }
            sb.append('\n');
        }
        return sb.toString();
    }

    @Override
    public Integer E() {
        return edgeTotal;
    }

    @Override
    public List<PowerEdge> adjectives() {
        Set<PowerEdge> set = new HashSet<>();
        for (Map.Entry<Integer, List<PowerEdge>> entry : this.adjs.entrySet()) {
            set.addAll(entry.getValue());
        }
        LinkedList<PowerEdge> powerEdges = new LinkedList<>(set);
        return powerEdges;
    }

    @Override
    public List<PowerEdge> adj(Integer w) {
        return this.adjs.getOrDefault(w, null);
    }

    @Override
    public PowerEdge getEdge(int v, int w) {
        List<PowerEdge> list = adj(v);
        for (PowerEdge edge : list) {
            if (edge.hasNode(w)) {
                return edge;
            }
        }
        return null;
    }

    @Override
    public int nodeLength() {
        return adjs.size();
    }
}
